<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
</body>
<script>
    // new关键词做了哪些操作?
    // 1. 创建一个纯净的实例化对象(空对象 {})
    // 2. 给实例化对象绑定原型属性(新版本:[[Prototype]],老版本浏览器:__proto__) 指向构造函数的原型对象
    //    可以理解为 => 所有的实例化对象都有一个原型属性([[Prototype]])指向构造函数的原型对象 => 所有的实例化对象 都可以通过此属性访问构造函数的原型对象上公用的属性和方法
    // 3. 将this指向创建的实例化对象 this -> {}  (对象是引用类型 通过将关键词this指向创建的对象 ,后续可以给创建的对象添加数据)
    // 4. 返回创建的实例化对象
    // 注意:
    // 1. 每次调用构造函数,都会重新执行构造函数的上下文 => 不同的实例化对象
    // 2. 构造函数中的this指向本次构造函数执行过程中创建的实例化对象 
    // 3. 为了区分普通函数和构造函数 要求构造函数首字母大写


    function Fn(a, b) {
        // {}
        // {}[[Prototype]] = Fn.prototype      {}.__proto__ = Fn.prototype
        // this -> {}
        this.a = a  
        this.b = b  
        // {a,b}
        // return this  
    }
    Fn.prototype.toString = function () {
        return `(${this.x}, ${this.y}})`  
    }
    Fn.prototype.sum = function () {
        return this.a + this.b  
    }
    var x = new Fn(1, 2)  
    console.log(x)  
    var y = new Fn(10, 20)  
    console.log(y)  


    // 实例化对象访问属性和方法的机制:
    // 1. 实例化对象自己有先找自己的
    // console.log(x.a, x.b)  

    // 2. 自己没有 => 则顺着实例化对象的原型属性[[Prototype]]  找构造函数的原型对象(Cat.prototype)
    // var result = x.sum()  
    // console.log(result)  

    // 验证:
    // 老版本: 获取x y的原型属性[[Prototype]]
    console.log(x.__proto__)
    console.log(y.__proto__)

    
    console.log(x.__proto__ === Fn.prototype)
    console.log(y.__proto__ === Fn.prototype)

    // 新版本: [[Prototype]] 不能手动取值 只能借助官方的方法
    // Object.getPrototypeOf(obj)  传入一个对象  返回该对象的原型属性的指向

    console.log(Object.getPrototypeOf(x) === Fn.prototype)
    console.log(Object.getPrototypeOf(y) === Fn.prototype)



</script>

</html>